const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader')
// 抽离单独的css文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 对css代码进行压缩
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
// 对js代码进行压缩
const TerserPlugin = require('terser-webpack-plugin');
// gzip压缩插件
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
    // 关闭webpack的性能提示
    performance: {
        // 关闭webpack的性能提示
        hints: false,
        // 设置入口文件导入文件体积阈值
        // maxEntrypointSize: 512000,
        // 设置资源文件的体积阈值
        // maxAssetSize: 512000
    },
    // development: 开发模式, production: 生产模式(对代码进行压缩,混淆)
    mode: process.env.NODE_ENV,
    // 开发环境,
    // 打包入口文件
    entry: "./src/index.js",
    // 打包输出文件
    output: {
        // 需要一个绝对路径
        path: path.join(__dirname, "dist"),
        // [name] [id] [hash] [contenthash]
        // [name] 表示入口文件的名称
        // filename: "[contenthash:10].bundle.js",
        // 指定同步导入模块的名称
        filename: "[name].bundle.js",
        // 指定异步导入模块的名称
        chunkFilename: "[name].chunk.js",
        // 自动清空dist目录
        clean: true
    },
    module: {
        rules: [
            // 匹配.vue文件, 调用vue-loader处理
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            },
            // 匹配css代码, 调用 style-loader和css-loader处理
            {
                // test: /\.(css|scss|sass)$/i,
                test: /\.(c|s[ac])ss$/i,
                // 从右往左执行
                // style-loaderjiang处理后的css代码通过style标签的方式插入到html页面中
                // use: ['style-loader', 'css-loader'],
                // MiniCssExtractPlugin.loader:将css文件通过link标签的方式引入html
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'sass-loader'
                ],
            },
            {
                test: /\.(png|jpg|jpeg|gif|svg|webp)/,
                // 会根据资源文件的大小, 决定生成base64还是生成图片文件
                type: 'asset'
            }
        ]
    },
    // 注册插件
    plugins: [
        new HtmlWebpackPlugin({
            // 指定模板html
            template: "./public/index.html",
            title:"webpack配置及性能优化"
        }),
        // 注册vue-loader插件
        new VueLoaderPlugin(),
        // 抽离单独的css文件
        new MiniCssExtractPlugin({
            // 抽离出来的css文件的名称(直接引用文件的名称)
            filename: "[contenthash:8].css",
            // 抽离出来的css文件的名称的前缀（间接引用的文件名称）
            chunkFilename: "[contenthash:8].css"
        }),
        // 注册gzip压缩插件
        new CompressionPlugin()
    ],
    // 开发服务器
    devServer: {
        // 指定端口号
        port: 9000,
        // 自动打开浏览器
        open: true,
        // 对资源进行压缩输出
        compress: true,
        // 默认值为true, 开启热更新( 模块热重载/替换 HMR: HOT Module Replacement)
        hot: false,
        // 配置代理
        // proxy: {}
    },
    // 优化配置
    optimization: {
        // 是否开启压缩功能, 默认开发模式下不进行压缩, 生产模式下默认开启压缩
        // 如果希望开发模式下开启压缩, 将该配置项设置为true
        // minimize: process.env.NODE_ENV==='production',
        minimizer: [
            // 在 webpack@5 中，你可以使用 `...` 语法来扩展现有的 minimizer（即 `terser-webpack-plugin`），将下一行取消注释
            // `...`,
            new CssMinimizerPlugin(),
            new TerserPlugin({
                // 启用/禁用多进程并发运行功能进行js代码压缩
                parallel: true,
                terserOptions: {
                    compress: {
                        // 移除console日志
                        drop_console: true,
                    },
                    format: {
                        // 移除js代码中注释
                        comments: false,
                    },
                },
                // 移除js代码中的注释
                extractComments: false,
            }),
        ],
        // 代码分割配置
        splitChunks: {
            // 异步代码分割
            // async: 默认值, 表示只有是异步导入的模块, 才拆分单独的文件
            // all: 表示同步和异步导入的模块, 都拆分单独的文件, 同步和异步模块可以复用
            // initial: 表示同步和异步导入的模块, 都拆分单独的文件, 同步和异步模块不能复用
            chunks: 'all',
            // 生成的chunk的最小体积, 单位字节
            minSize: 200000,
            // 生成的chunk的最大体积, 单位字节
            maxSize: 300000,
            // 用于设置引用阈值，被引用次数超过该阈值的 Module 才会进行分包处理
            minChunks: 1,
            // 限定异步模块拆分的子模块的数量
            maxAsyncRequests: 10,
            // 限定异步模块拆分的子模块的数量
            maxInitialRequests: 10,
            // 生成的chunk的名称的连接符
            automaticNameDelimiter: '~',
            // 缓存组: 拆分模块的规则
            cacheGroups: {
                defaultVendors: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    // 设置优先级, 优先级越高, 优先匹配
                    priority: 10,
                    // 复用已存在的模块
                    reuseExistingChunk: true,
                }
            }
        },
    },
    // 排除第三方库， 避免二次打包, 直接引入在线cdn
    externals: {
        vue: 'Vue',
        vuex: 'Vuex',
        'vue-router': 'VueRouter',
        axios: 'axios',
        'element-plus': 'ElementPlus'
    }
}